package org.candan.spider.task.spider;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.net.ftp.FTPFile;
import org.apache.log4j.Logger;
import org.candan.spider.bean.DataSift;
import org.candan.spider.bean.Plan;
import org.candan.spider.bean.Result;
import org.candan.spider.bean.TagSift;
import org.candan.spider.bean.Task;
import org.candan.spider.task.Container;
import org.candan.spider.task.xml.XMLProperty;
import org.candan.spider.util.DateUtil;
import org.candan.spider.util.PropertyParse;
import org.candan.spider.util.SLog;



public class SpiderPlan extends TimerTask {

	private Logger logger = new SLog("SpiderPlan").getLogger();  
	private Plan plan;
	private DataSift df;
	private TagSift tf;
	public int downNum=1;
	private String dateRegex=null;
	private boolean isSinglePlan = false;
	private TagFilter tfter = new TagFilter();
	public SpiderPlan(Plan plan ) {
		super();
		this.plan = plan;
		df=Container.tasks.get(plan.getParent()).getDatafilter();
		tf=Container.tasks.get(plan.getParent()).getTagFilter();
	}
	
	public SpiderPlan(Plan plan,DataSift dst, TagSift tsf){
		super();
		this.plan = plan;
		this.df = dst;
		this.tf = tsf;
		isSinglePlan = true;
	}
	@Override
	public void run() {
		logger.info(plan.getId()+"开始执行。。。！");
		//如果此任务不是在等待运行，则跳过
		if(!plan.getStatus().equals(XMLProperty.STATUS_WAIT)){
			logger.info(plan.getId()+"  不是正在等待运行任务，完成。。。！");
		}
		else{
			plan.setStatus(XMLProperty.STATUS_BEGIN);
			if(!isSinglePlan)Container.updatePlan(plan);
			logger.info(plan.getId()+"....开始下载计划。。。！");
			
			// 调用下载功能，没下载完一个文件变添加一个result
			execueSpiderPlan(plan.getUrl(),plan.getOutput());
			
			//下载完后调用更新计划
			plan.setStatus(XMLProperty.STATUS_FINISH);
			plan.setEndTime(new Date());
			if(!isSinglePlan)Container.updatePlan(plan);
			logger.info(plan.getId()+"....完成下载计划。。。！");
		}
		logger.info(plan.getId()+"执行完成。。。！");
		this.cancel();
		plan.getTimer().cancel();
	}
	
	/**
	 * @category 解析标签
	 * @return
	 */
	public Map<String,String> tagExtract(){
		return  tfter.extractTag(plan.getUrl(), tf.getTag(), tf.getKeywords().replace("，", ",").split(","));
	}
	
//	/**
//	 * @category
//	 * @param ftps
//	 * @return
//	 */
//	public List<FTPFile> ftpExtract(FTPFile[] ftps){
//		List<FTPFile> files = new LinkedList<FTPFile>();
//		for(int i =0; i <  ftps.length; i++){
//			if(dataFilterBasicCheck(ftps[i].getName())){
//				files.add(ftps[i]);
//			}
//		}
//	
//		return files;
//	}
	/**
	 * @category 每个计划下载数量检查-数据过滤条件之一
	 * @return
	 */
	protected boolean dataFilterDownNumCheck(){
		if(df == null)return true;//没有设置数据过滤条件
		if(df.getMaxDownload() == 0)return true;//没有设置下载文件数目
		if(df.getMaxDownload() < downNum)return false;
		return true;//大于下载数量
	}

	 /**
	  * @category 数据过滤条件检查-数据起止时间、关注时间范围、一次计划下载个数
	 * @param file
	 * @return
	 */
	protected boolean dataFilterBasicCheck(String file){
		// 没有设置数据过滤，返回true
		if(df == null)return true;
		//有日期提取格式
		if(df.getRegex() != null && !df.getRegex().trim().equals("")){
			//是否能从文件名中提取时间
			Date date = extractDateFromStr(file);
			if(date == null)return false;
			//判断数据的起始时间
			if(df.getFromDate() != null){
				if(date.getTime() < df.getFromDate().getTime())return false;
			}
			//判断数据的终止时间
			if(df.getToDate() != null){
				if(date.getTime() > df.getToDate().getTime())return false;
			}
			//判断数据的有效时间范围
			if(df.getRange() !=0){
				
				logger.info("数据有效时间："+df.getRange());
				if(date.getTime() < (plan.getStartTime().getTime() - df.getRange() * 24 * 3600*1000))return false;
			}
			
		}
		//检查数据是否包含关键字
		if(df.getKeywords() != null && !"".equals(df.getKeywords().trim())){
			for(String key : df.getKeywords().replace("，", ",").split(",")){
				if(!file.toLowerCase().contains(key.toLowerCase().trim()))return false;
			}
		}
		return true;
	}

	/**
	 * @category 记录下载结果
	 * @param name
	 * @param size
	 * @param path
	 */
	public void addResult(String name, String size, String path){
		if(isSinglePlan)return;
		Result rs = new Result();
		rs.setName(name);
		rs.setSize(size);
		rs.setPath(path);
		plan.getResult().add(rs);
		downNum++;
	}
	
	/**
	 * @category 执行下载计划
	 * @param url
	 * @param output
	 */
	protected void execueSpiderPlan(String url, String output){
		
	}
	
	
	/**
	 * @category 锁定下载文件-下载前
	 * @param file
	 * @return
	 */
	synchronized public boolean lockFile(File file){
		File lock =new File(file.getAbsoluteFile()+".LOCK");
		if(lock.exists()){
			if(new Date().getTime() - file.lastModified() > 30*60*1000)return true;
			return false;
		}else{
			try {
				lock.createNewFile();
//				logger.info("计划("+plan.getId()+")下载："+file.getAbsolutePath());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}
		}
		return true;
	}
	
	protected boolean isExistWholeFile(File localFile, long remoteSize){
		if(localFile.exists()&& localFile.length() >= remoteSize){
			return true;
		}
		if(!isSinglePlan)logger.info("计划("+plan.getId()+")下载("+downNum+" / "+df.getMaxDownload()+")："+localFile.getAbsolutePath());
		return false;
	}
	/**
	 * @category 释放文件锁-下载后
	 * @param f
	 */
	protected void releaseLock(File f){
		new File(f.getAbsoluteFile()+".LOCK").delete();
	}
	
	
	/**
	 * @category 提取时间-文件名
	 * @param fileName 文件名
	 * @return
	 */
	private Date extractDateFromStr(String fileName){
		Pattern p = Pattern.compile(generateRegex(df.getRegex())); 
		Matcher m = p.matcher(fileName); 
		while(m.find()){
			try {
				return new SimpleDateFormat(df.getRegex()).parse(m.group());
			} catch (ParseException e) {
				e.printStackTrace();
				return null;
			}
		}
		return null;
	}
	
//	/**
//	 * @category 由时间格式符生成正则表达式
//	 * @param match 日期格式： yyyyMMdd HH:mm:ss
//	 * @return
//	 */
//	public String generateRegex2(String match){
//		if(dateRegex == null){
//			dateRegex = "";
//		char[] ch =match.toCharArray();
//		
//		int i =0;
//		String ori = "";
//		for(int j = 0; j < ch.length; j++){
//			if(!ori.equalsIgnoreCase(ch[j]+"") && i !=0){
//				dateRegex += "{"+i+"}";
//				i=0;
//			}
//			
//			if((ch[j]+"").equalsIgnoreCase("y")){
//				if(!ori.equalsIgnoreCase(ch[j]+"")){
//					ori = ch[j] + "";
//					dateRegex+="\\d";
//				}
//				i++;
//			}else if((ch[j]+"").equalsIgnoreCase("M")){
//				if(!ori.equalsIgnoreCase(ch[j]+"")){
//					ori = ch[j] + "";
//					dateRegex+="\\d";
//				}
//				i++;
//			}else if((ch[j]+"").equalsIgnoreCase("d")){
//				if(!ori.equalsIgnoreCase(ch[j]+"")){
//					ori = ch[j] + "";
//					dateRegex+="\\d";
//				}
//				i++;
//			}else if((ch[j]+"").equalsIgnoreCase("H")){
//				if(!ori.equalsIgnoreCase(ch[j]+"")){
//					ori = ch[j] + "";
//					dateRegex+="\\d";
//				}
//				i++;
//			}else if((ch[j]+"").equalsIgnoreCase("s")){
//				if(!ori.equalsIgnoreCase(ch[j]+"")){
//					ori = ch[j] + "";
//					dateRegex+="\\d";
//				}
//				i++;
//			}else if((".*+^$\\").indexOf(ch[j]+"") >=0){
//				dateRegex+= "\\"+ch[j];
//			}else{
//				dateRegex+= ch[j];
//			}
//			
//		}
//		if(i!=0){
//			dateRegex +="{"+i+"}";
//		}
//		}
//		dateRegex = "\\d{8}";
//		logger.info("日期正则表达式："+dateRegex);
//		return dateRegex;
//	}
	
	public  String generateRegex(String match){ //.*+^$?\\
		
		if(dateRegex == null){
			dateRegex = "";
			int index = 0;
	//		String regex="";
			String splitChar ="";
			match = match.replace("'", "");
			String[] str = match.split(PropertyParse.getValue("preproccess.date.split.match"));// +\\.*!@#\\
			for(String s: str){
				index += s.length();
				if(s.length() !=0){
					dateRegex += "\\d{"+s.length()+"}";
				}
				if(index + 1 > match.length())break;
				splitChar = match.substring(index, index+1);
				if(".*+^$?\\".indexOf(splitChar) >=0){
					dateRegex +=  "\\";
				}
				dateRegex += match.substring(index, index+1);	
				index++;
				
			}
			logger.info("日期格式为:"+match);
			logger.info("日期正则表达式为:"+dateRegex);
		}
		return dateRegex;
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		boolean bs =new SpiderPlan(null).checkfile(new File("20120326-UKMO20111012-L4HRfnd-GLOB-v01-fv02-OSTIA.nc.bz2"));
//		System.out.println(bs);
//		System.out.println(	"xsaf-.".toCharArray().length);
		String str= "yyyyMMdd";
//		SpiderPlan.generateRegex2("20100205   12::51:15");
//		SpiderPlan sp = new SpiderPlan(null);
		
//		System.out.println(SpiderPlan.generateRegex(str));
//		System.out.println(".".indexOf("sf."));
	}

}
